package com.xframe.event.bus.core.msg;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.xframe.event.bus.core.model.DataMessage;
import lombok.extern.log4j.Log4j2;
import org.springframework.lang.Nullable;

import java.io.IOException;

/**
 * 功能描述:消息发送者
 *
 * @author xufeng
 * @version 1.0
 * 2022-09-26
 */
@Log4j2
public class MessageSender implements AutoCloseable {


    private static final String CHARSET_NAME = "utf-8";
    private Connection msgConn;
    private Channel curChannel;

    private MessageSender(Connection connection){
        msgConn = connection;
    }

    public static void init() throws IOException {
        messageSender = new MessageSender(ConnectFactory.getMsgConn());
        messageSender.curChannel = messageSender.msgConn.createChannel();
        log.info("Channel init OK");
    }

    private static MessageSender messageSender;

    public static MessageSender getMessageSender(){
        return messageSender;
    }

    /**
     * 发送消息到指定的队列
     *
     * @param queueName  列队的名称
     * @param msg  发送的消息
     *
     */
    public void sendMsg(String queueName, String msg){
        try {
            //this.curChannel.queueDeclare(queueName, true, false, false, null);
            this.curChannel.basicPublish("", queueName, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息到指定的队列
     *
     * @param queueName  列队的名称
     * @param dataMessage  发送的消息
     *
     */
    public void sendMsg(String queueName, DataMessage dataMessage){
        try {
            //String msg = JSON.toJSONString(dataMessage);
            String msg = JSONUtil.toJsonStr(dataMessage);
            this.curChannel.basicPublish("", queueName, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息到指定的队列
     *
     * @param queueName  列队的名称
     * @param msg  发送的消息
     * @param properties  发送消息的设置 可以为空
     *
     */
    public void sendMsg(String queueName, String msg,@Nullable AMQP.BasicProperties properties){
        try {
            //this.curChannel.queueDeclare(queueName, true, false, false, null);
            this.curChannel.basicPublish("", queueName, properties, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送广播消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为fanout类型
     * @param msg  发送的消息
     * @param properties  发送消息的设置 可以为空
     *
     */
    public void sendBroadcastMsg(String exchangeName, String msg,@Nullable AMQP.BasicProperties properties){
        try {
            this.curChannel.basicPublish(exchangeName, "", properties, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 发送广播消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为fanout类型
     * @param msg  发送的消息
     *
     */
    public void sendBroadcastMsg(String exchangeName, String msg){
        try {
            this.curChannel.basicPublish(exchangeName, "", null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送广播消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为fanout类型
     * @param dataMessage  发送的消息
     *
     */
    public void sendBroadcastMsg(String exchangeName, DataMessage dataMessage){
        try {
            String msg = JSON.toJSONString(dataMessage);
            this.curChannel.basicPublish(exchangeName, "", null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为Direct类型
     * @param routingKey 路由key值
     * @param msg  发送的消息
     * @param properties  发送消息的设置 可以为空
     *
     */
    public void sendRoutingMsg(String exchangeName,String routingKey, String msg,@Nullable AMQP.BasicProperties properties){
        try {
            this.curChannel.basicPublish(exchangeName, routingKey, properties, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为Direct类型
     * @param routingKey 路由key值
     * @param msg  发送的消息
     *
     */
    public void sendRoutingMsg(String exchangeName,String routingKey, String msg){
        try {
            this.curChannel.basicPublish(exchangeName, routingKey, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为Direct类型
     * @param routingKey 路由key值
     * @param dataMessage  发送的消息
     *
     */
    public void sendRoutingMsg(String exchangeName,String routingKey, DataMessage dataMessage){
        try {
            String msg = JSON.toJSONString(dataMessage);
            this.curChannel.basicPublish(exchangeName, routingKey, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为topic类型
     * @param routingKey 路由key值
     * @param msg  发送的消息
     * @param properties  发送消息的设置 可以为空
     */
    public void sendTopicMsg(String exchangeName, String routingKey, String msg, @Nullable AMQP.BasicProperties properties){
        try {
            this.curChannel.basicPublish(exchangeName, routingKey, properties, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为topic类型
     * @param routingKey 路由key值
     * @param msg  发送的消息
     */
    public void sendTopicMsg(String exchangeName, String routingKey, String msg){
        try {
            this.curChannel.basicPublish(exchangeName, routingKey, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送路由消息
     *
     * @param exchangeName  交换机的名字 交换机必须设置为topic类型
     * @param routingKey 路由key值
     * @param dataMessage  发送的消息
     */
    public void sendTopicMsg(String exchangeName, String routingKey, DataMessage dataMessage){
        try {
            String msg = JSON.toJSONString(dataMessage);
            this.curChannel.basicPublish(exchangeName, routingKey, null, msg.getBytes(CHARSET_NAME));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    @Override
    public void close() throws Exception {
        if (curChannel != null) {
            curChannel.close();
            curChannel = null;
        }
        if (msgConn != null) {
            msgConn.close();
            msgConn = null;
        }
    }
}
